#include <iostream>
#include <fstream>
#include <chrono>
#include <thread>
#include "utils/rabbitmq_client.hpp"
#include "utils/oss_client_manager.hpp"
#include "utils/file_utils.hpp"
#include "database/db_connection.hpp"
#include "database/file_dao.hpp"
#include "common/config.hpp"
#include <nlohmann/json.hpp>

using json = nlohmann::json;

void process_message(const std::string& msg) {
    try {
        json msg_json = json::parse(msg);
        std::string hashcode = msg_json.at("hashcode");
        
        std::string source_file_path = Config::UPLOAD_PATH + hashcode;
        std::cout << "[+] Received task. Backing up file: " << source_file_path << std::endl;

        std::string content = FileUtils::readFile(source_file_path);
        if (content.empty()) {
            std::cerr << "[-] Error: Failed to read source file or file is empty: " << source_file_path << std::endl;
            return;
        }

        bool upload_ok = OssClientManager::getInstance()->uploadFile(hashcode, content);
        if (!upload_ok) {
            std::cerr << "[-] Error: Failed to upload to OSS for hash: " << hashcode << std::endl;
            return;
        }
        
        // 在“备份”模型下，我们不删除本地文件，也不再需要更新数据库状态
        std::cout << "[OK] Successfully backed up file to OSS: " << hashcode << std::endl;
    } catch (const std::exception& e) {
        std::cerr << "[-] Error processing message: " << e.what() << std::endl;
    }
}

int main() {
    if (!Config::load()) { /* ... */ return 1; }
    if (!DBConnection::getInstance()->connect()) { /* ... */ return 1; }
    OssClientManager::getInstance()->init();
    
    RabbitMQClient mq(Config::RABBITMQ_URI, Config::RABBITMQ_EXCHANGE, Config::RABBITMQ_QUEUE, Config::RABBITMQ_ROUTING_KEY);
    
    std::cout << "Transfer service (Backup Worker) started. Listening for messages..." << std::endl;

    while (true) {
        std::string msg = mq.consume();
        if (!msg.empty()) {
            process_message(msg);
        } else {
            std::this_thread::sleep_for(std::chrono::seconds(1));
        }
    }
    return 0;
}
